import { scheduleUpdateOnFiber } from "./fiberWorkLoop";
import { ClassComponent, Fragment, FunctionComponent, HostComponent, HostText } from "./workTags";
import { isFn, isStrOrNum, isUndefined } from "../shared/utils";
import { Placement } from "../shared/reactFlags";

export interface IFiber {
  type: any;
  props: any;
  key: string | null;
  return: any;
  child: any;
  sibling: any;
  alternate: any;
  stateNode: any;
  tag: any;
  index: any;
  flags: any;
  updateQueue: any;
  memorizedState: any;
}

/**
 * 根据fiber的type属性计算出tag
 */
function handleFiberTag(fiber: any): void {
  const type = fiber.type;

  if (isStrOrNum(type)) {
    // 原生标签
    fiber.tag = HostComponent;
  } else if (isFn(type)) {
    // isReactComponent 为 true 证明是类组件
    fiber.tag = type.prototype.isReactComponent ? ClassComponent : FunctionComponent;
  } else if (isUndefined(type)) {
    // 为文本节点
    fiber.tag = HostText;

    // 文本节点是没有 props 属性的，我们将手动的给该 fiber 设置一个 props 属性
    fiber.props = {
      children: fiber,
    };
  } else {
    fiber.tag = Fragment;
  }
}

/**
 *
 * @param vdom 虚拟dom节点
 * @param returnFiber 父fiber
 * @returns
 */
export function createFiber(vdom: JSX.Element, returnFiber: any) {
  const fiber: IFiber = {
    type: vdom.type,
    props: vdom.props,
    key: vdom.key,

    // 父 fiber
    return: returnFiber,

    // 子 fiber
    child: null,

    // 兄弟 fiber
    sibling: null,

    // 对应后缓冲区的 fiber
    alternate: null,

    // 真实 dom
    stateNode: null,

    // tag
    tag: null,

    // 当前层级的位置
    index: null,

    flags: Placement,

    updateQueue: null,
    memorizedState: null
  };
  // 计算fiber的tag
  handleFiberTag(fiber);

  return fiber;
}

export function updateContainer(vdom: JSX.Element, container: HTMLElement) {
  // 1. 创建根fiber
  const fiberRoot = createFiber(vdom, {
    // 该对象就是我的父 fiber 对象，里面会放置一些核心的属性
    type: container.nodeName.toLowerCase(),
    stateNode: container,
  });

  scheduleUpdateOnFiber(fiberRoot);
}
